perm filename PUPR.C[11,HE] blob sn#688205 filedate 1982-12-06 generic text, type T, neo UTF8
/* LINTLIBRARY */
/*
 * pupread.c
 *
 * Reads a pup packet and returns the information in it.
 * Since a lot of this information is superfluous, the user
 * can pass NULL as the address for the data to be returned
 * for any item(s) not wanted.  The input parameters are
 * guaranteed not to be altered unless the return status
 * is OK, or the status is BADCKSUM and the channel status
 * includes PCM_IGNBADCKS.
 *
 * Jeffrey Mogul & Dan Kolkowitz	12-January-1981
 *
 * modified JCM	30-June-1981 -- neglected to return bad status
 *
 */

#include <puppacket.h>
#include <pupconstants.h>
#include <pupstatus.h>

pupread(Pchan,buf,buflen, Ptype, ID, DstPort, SrcPort)
struct PupChan	*Pchan;				/* channel to use */
char		*buf;				/* data buffer */
int		*buflen;			/* data buffer length */
uchar		*Ptype;				/* Pup type */
ulong		*ID;				/* Pup ID */
struct Port	*DstPort;			/* destination port */
struct Port	*SrcPort;			/* source port */
{
	struct	EnPacket enpack;	/* ether encapsulation */
	int	readstat;
	int	rlen;			/* rounded length of pup data */

	/*
	 * here we would switch on the Chan->transport to
	 * determine which lower-level encapsulation to use
	 * if there were any choice.
	 */
	
#ifdef	VAX
	if (Pchan->TimeoutSet)
	    readstat = enreadquick(Pchan->ifid, & enpack, NULL);
	else {	/* must set timeout */
	    readstat = enread(Pchan->ifid, & enpack, NULL, Pchan->timeout);
	    Pchan->TimeoutSet = 1;
	}
#else
	readstat = enread(Pchan->ifid, & enpack, &(Pchan->filter.en),
				Pchan->timeout);
#endif

	if (readstat==OK) {	/* return all information requested */

		rlen = roundup(enpack.Pup.PupLength) - PUPACKOVER;

		if (rlen < 0)	/* avoid negative length copies */
			return(NOTAPUP);

		/*
		 * check the pup checksum if necessary.
		 * If the checksum is bad, set the status to BADCKSUM.
		 * If the channel mode include IGNBADCKS and the checksum
		 * is bad, don't modify any params.
		 */
		if (Pchan->mode&PCM_RCHECKSUM) {
			ushort cksum = *(short *)&enpack.Pup.PupData[rlen];
			if (cksum != NOCKSUM &&
			    cksum != checksum(&enpack.Pup,rlen+PUPACKOVER-2)) {
				readstat = BADCKSUM;
				if (Pchan->mode&PCM_IGNBADCKS)
				    return(readstat);
				    }
			}
		/*
		 * return each parameter iff reference address is not NULL
		 */
		
		if (SrcPort) {
			PortUnpack(&enpack.Pup.PupSrc, SrcPort);
			}
		
		if (DstPort) {
			PortUnpack(&enpack.Pup.PupDst, DstPort);
			}
		
		if (ID) *ID = getlong(enpack.Pup.PupID);

		if (Ptype) *Ptype = enpack.Pup.PupType;

		if (buflen) *buflen = enpack.Pup.PupLength - PUPACKOVER;
			/* return unrounded length */

		if (buf) {	/* return buffer to user */

			bmove(enpack.Pup.PupData,buf,rlen);

#ifdef	PUP__NNSO	/* nonstandard byte order */
		
			if (Pchan->mode&PCM_RFIXLAST)
				/* swap last word in buffer if odd length */
				if (enpack.Pup.PupLength&1) {
				    /* swap garbage byte */
				    buf[enpack.Pup.PupLength-1] =
					buf[enpack.Pup.PupLength];
					}
#else			/* no trouble for standard byte order */
#endif
			}

		return(readstat);
	}
	return(readstat);
}